/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.web.ext.echarts.builder.impl;

import cn.easyplatform.web.ext.ComponentHandler;
import cn.easyplatform.web.ext.echarts.ECharts;
import cn.easyplatform.web.ext.echarts.builder.TemplateUnit;
import cn.easyplatform.web.ext.echarts.lib.Dataset;
import cn.easyplatform.web.ext.echarts.lib.Option;
import cn.easyplatform.web.ext.echarts.util.CreateModelUtils;
import cn.easyplatform.web.ext.echarts.util.GsonUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.apache.commons.lang3.ArrayUtils;

import java.util.*;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public class LineChartsBuilder extends AbstractChartsBuilder {

    private static final boolean DEBUG = false;
    private static final List<List<Object>> source = new ArrayList<>();

    static {
//        List<Double> xAxisList = Arrays.asList(0.010958904109589041,
//                0.021917808219178082,
//                0.0410958904109589, 0.06027397260273973,
//                0.08767123287671233, 0.1643835616438356,
//                0.2493150684931507, 0.4986301369863014,
//                0.7506849315068493, 1.0082191780821919,
//                1.4986301369863013, 2.0054794520547947,
//                3.0027397260273974);
//        List<Double> seriesList1 = Arrays.asList(0.022855306567755678,
//                0.009543563533718213, 0.007129236656789046,
//                0.005760359482119352, 9.384336357587369E-4,
//                0.004717251947316912, 0.0055252164055168175,
//                0.0070102572177388155, 0.008139946181543978,
//                0.008835679579988449, 0.009243996658959724,
//                0.01000313902215268, 0.011148755509375635);
//        List<Double> seriesList2 = Arrays.asList(0.855307567755678,
//                0.543563522718213,
//                0.129236655489046, 0.760359464119352,
//                9.3363576347369E-4, 0.731551988316912,
//                0.5233164055258175, 0.010257273638155,
//                0.139959181543978, 0.839679579648449,
//                0.243955658959724, 0.00367902215268,
//                0.148784509375635);
//        for (int i = 0; i < xAxisList.size(); i++) {
//            List<Object> valueList = new ArrayList<>();
//            valueList.add(xAxisList.get(i));
//            valueList.add(seriesList1.get(i));
//            valueList.add(seriesList2.get(i));
//            source.add(valueList);
//        }
//        System.out.println(source.toString());
    }

    public LineChartsBuilder(String type) {
        super(type);
    }

    @Override
    protected void setSeries(Option option, String name, JsonArray data) {
        if (name.equals("confidence-band")) {
            createConfidenceBand(option, (JsonArray) data);
        } else
            super.setSeries(option, name, data);
    }

    private void createConfidenceBand(Option option, JsonArray data) {
        int base = 3;
        Object[] axis = new Object[data.size()];
        Object[] series0 = new Object[data.size()];
        Object[] series1 = new Object[data.size()];
        Object[] series2 = new Object[data.size()];
        for (int i = 0; i < data.size(); i++) {
            JsonObject map = (JsonObject) data.get(i);
            axis[i] = map.get("date").getAsString();
            series0[i] = map.getAsJsonPrimitive("l").getAsDouble() + base;
            series1[i] = map.getAsJsonPrimitive("u").getAsDouble() - map.getAsJsonPrimitive("l").getAsDouble();
            series2[i] = map.getAsJsonPrimitive("value").getAsDouble() + base;
        }
        setData(option.getxAxis(), axis, 0);
        setData(option.getSeries(), series0, 0);
        setData(option.getSeries(), series1, 1);
        setData(option.getSeries(), series2, 2);
    }


    @Override
    public void build(ECharts charts, ComponentHandler dataHandler) {
        if (DEBUG) {
            charts.setData(source);
            createDataset(charts, dataHandler);
        } else if (charts.getData() != null) {
            createDataset(charts, dataHandler);
//            TemplateUnit template = getTemplate(charts.getTemplate());
//            template.setJson(charts.getData().toString());
//            super.build(charts.getOption(), template, true);
        } else if (dataHandler == null) {
            build(charts.getOption(), getTemplate(charts.getTemplate()), true);
        } else if (charts.getOption().getDataset() != null) {
            super.createDataset(charts, dataHandler);
        } else if (charts.getQuery() != null) {
            List<Map> data = dataHandler.selectList0(Map.class, charts.getDbId(), (String) charts.getQuery());
            CreateModelUtils.barlineCreateModel(charts, data);
        } else if (charts.getOption().getSeries() instanceof List) {
            List<?> series = (List<?>) charts.getOption().getSeries();
            Set<Object> legend = new HashSet<>();
            for (Object serie : series) {
                Map<String, Object> line = (Map<String, Object>) serie;
                if (line.get("query") != null) {
                    Object[] data = dataHandler.selectOne(Object[].class, charts.getDbId(), (String) line.remove("query"));
                    if (!(data[0] instanceof Number)) {
                        legend.add(data[0].toString());
                        line.put("name", data[0].toString());
                        line.put("data", ArrayUtils.subarray(data, 1, data.length));
                    } else
                        line.put("data", data);
                }
            }
            if (!legend.isEmpty() && charts.getOption().getLegend() != null && "data".equals(charts.getOption().getLegend().getData()))
                charts.getOption().getLegend().setData(legend);
        }
    }

    @Override
    protected void createDataset(ECharts echarts, ComponentHandler dataHandler) {
        if (!(echarts.getData() instanceof List)
                || ((List) echarts.getData()).isEmpty()) {
            return;
        }
        List<List<Object>> sourceList = (List<List<Object>>) echarts.getData();
        Dataset dataset = new Dataset();
        List<Object> objectList = sourceList.get(0);
        // source列表第一位一定是xAxis的值
        // 使用dataset必须把series和xAxis的data清除
        // 清除xAxis的data
        Map xAxis = null;
        if (echarts.getOption().getxAxis() instanceof Map) {
            xAxis = (Map) echarts.getOption().getxAxis();
        } else if (echarts.getOption().getxAxis() instanceof List) {
            xAxis = (Map) ((List) echarts.getOption().getxAxis()).get(0);
        }
        if (xAxis != null) {
            xAxis.remove("data");
        }
        // 清除series的data
        List<Map> seriesList = new ArrayList<>();
        Map series = null;
        if (echarts.getOption().getSeries() instanceof Map) {
            series = (Map) echarts.getOption().getSeries();
        } else if (echarts.getOption().getSeries() instanceof List) {
            series = (Map) ((List) echarts.getOption().getSeries()).get(0);
        }
        // source列表长度减一就是series的数量
        // 根据数据长度增加series数量
        for (int i = 0; i < objectList.size() - 1; i++) {
            if (series != null) {
                series.remove("data");
            }
            seriesList.add(series);
        }
        echarts.getOption().setSeries(seriesList);
        dataset.setSource(echarts.getData());
        if (echarts.getOption().getDataset() != null) {
            echarts.getOption().setDataset(null);
        }
        echarts.getOption().setDataset(dataset);
    }
}
